/*
 * =====================================================================================
 *
 *       Filename:  utils.cpp
 *
 *    Description:  utilities (calculate correlation coefficient, expectation, variance, etc)
 *
 *        Version:  1.0
 *        Created:  08/07/2009 11:25:50 AM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Zhao Zhao
 *        Company:  ndssl
 *
 * =====================================================================================
 */
#pragma once

#include <string>
#include <vector>
#include <sstream>
#include "include.h"


using namespace std; 

/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  to_string
 *  Description:  everything to string
 * =====================================================================================
 */
template <typename T>
string to_string (const T& t)
{
	stringstream ss;
	ss << t;
	return ss.str();
}

                                              
/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  Average
 *  Description:  Calculate E(array)
 * =====================================================================================
 */

template <typename T, typename SizeT>
float Average(T array, SizeT size)
{
	float avg = 0;
	for(int i = 0; i<size; i++)
	{
		avg += array[i];
	}
	return avg/(float)size;
}

/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  CC
 *  Description:  Calculate correlation coefficient
 *  			  CC_ij=(E(A_i*A_j)-E(A_i)E(A_j))/sqrt(Var(A_i)Var(A_j))
 * =====================================================================================
 */
template <typename T, typename SizeT>
float CalcCC(T& array1, SizeT size1, T& array2, SizeT size2)
{
	float numerator = CrossAverage(array1, array2, size1)-Average(array1, size1)*Average(array2, size2);
	float denominator = sqrt(Variance(array1, size1)*Variance(array2, size2));
	return numerator/denominator;
}

/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  CrossAverage
 *  Description:  Calculate E(array1*array2)
 * =====================================================================================
 */
template <typename T, typename SizeT>
float CrossAverage(T array1, T array2, SizeT size)
{
	float avg = 0;
	for(int i = 0; i<size; i++)
	{
		avg += array1[i]*array2[i];
	}
	return avg/(float)size;
}

/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  Variance
 *  Description:  Calculate variance: Var(A_i)=E(A_i^2)-E^2(A_i)
 * =====================================================================================
 */
template <typename T, typename SizeT>
float Variance(T array, SizeT size)
{
	float avg_square = 0;
	for(int i = 0; i<size; i++)
	{
		avg_square += array[i]*array[i];
	}
	avg_square /= (float)size;
	return avg_square - Average(array, size)*Average(array, size); 
}


/* ---------------- FreeMem frees memory pointed by mem --------------------By Maleq---*/ 
template <typename T>
void  FreeMem(T &mem)
{
	if (mem)
		delete [] mem;
	mem = NULL; 
}



/* ------- FreeAll frees memory pointed by itself and its element -----------By Maleq---*/
template <typename T, typename SizeT>
void  FreeAll(T &mem, SizeT s)
{
	if (mem) {
		for (SizeT i=0; i<s; i++)
			delete [] mem[i];
		delete [] mem;
	}
	mem = NULL; 
}

/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  GetMax
 *  Description:  Reture max value and its index in an array
 * =====================================================================================
 */
template <typename T, typename sizeT>
void GetMax(T* array, sizeT size, T& max, sizeT& pos)
{
	max = 0;
	pos = 0;
	for(sizeT i = 0; i<size; i++)
	{
		if(max < array[i])
		{
			max = array[i];
			pos = i;
		}
	}
}

/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  GetMin
 *  Description:  Reture min value and its index in an array
 * =====================================================================================
 */
template <typename T, typename sizeT>
void GetMin(T* array, sizeT size, T& min, sizeT& pos)
{
	min = INT_MAX;
	pos = 0;
	for(sizeT i = 0; i<size; i++)
	{
		if(min > array[i])
		{
			min = array[i];
			pos = i;
		}
	}
}

/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  GetMean
 *  Description:  Reture mean value in an array
 * =====================================================================================
 */
template <typename T, typename sizeT>
void GetMean(T* array, sizeT size, T& mean)
{
//	mean = 0;		
//	for(sizeT i = 0; i<size; i++)
//	{
//		mean = mean + array[i];
//	}
//	mean = mean/i;
}


/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  GetMaxN
 *  Description:  Get N max value of an array, 
 *  			  record in result, and record the index in pos
 *  			  result and pos must be allocated space in advance
 * =====================================================================================
 */
template <typename T, typename sizeT>
void GetMaxN(T* array, sizeT size, T* result, sizeT* pos, sizeT N)
{
	
	T maxTmp;
	sizeT posTmp;
	GetMax(array, size, maxTmp, posTmp);
	result[0] = maxTmp;
	pos[0] = posTmp;
	for(sizeT i = 1; i<N; i++)
	{
		maxTmp = 0;
		for(sizeT j = 0; j<size; j++)
		{
			if(maxTmp < array[j] && array[j] <= result[i-1] && !Find(j, pos, i))
			{
				maxTmp = array[j];
				posTmp = j;
			}			
		}
		result[i] = maxTmp;
		pos[i] = posTmp;
	}
}


/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  Find
 *  Description:  whether an element is belong to an array
 * =====================================================================================
 */
template <typename T, typename sizeT>
bool Find(T val, T* array, sizeT size)
{
	for(sizeT i = 0; i<size; i++)
	{
		if(val == array[i]) return true;
	}
	return false;
}

